package com.eastfair.auth.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.eastfair.annotation.annotation.base.BaseControllerInfo;
import com.eastfair.annotation.base.SubjectTypeEnum;
import com.eastfair.auth.dto.*;
import com.eastfair.auth.entity.UserAccount;
import com.eastfair.auth.service.OrganizationService;
import com.eastfair.auth.service.UserAccountService;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.controller.SuperController;
import com.eastfair.cache.redis.RedisOps;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.echo.core.EchoService;
import com.eastfair.imaster.api.CompanyServiceFeign;
import com.eastfair.projectcore.api.ProjectCoreServiceFeign;
import com.eastfair.security.util.TenantUtil;
import com.eastfair.vo.VoGroupClass;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.eastfair.core.base.R.SUCCESS_CODE;
import static com.eastfair.core.exception.code.ExceptionCode.JWT_PARSER_TOKEN_FAIL;


/**
 * <p>
 * 前端控制器
 * 用户账户信息
 * </p>
 *
 * @author ligang
 * @date 2021-07-13
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/userAccount")
@Api(value = "UserAccount", tags = "用户账户信息")
//@PreAuth(replace = "auth:auth:")
public class UserAccountController extends SuperController<UserAccountService, Long, UserAccount, UserAccountPageQuery, UserAccountSaveDTO, UserAccountUpdateDTO> {

    @Autowired
    private EchoService echoService;

    @Autowired
    UserAccountService userAccountService;
    @Autowired
    TenantUtil tenantUtil;

    @Autowired
    ProjectCoreServiceFeign projectCoreServiceFeign;

    @Autowired
    CompanyServiceFeign companyServiceFeign;

    @Autowired
    OrganizationService organizationService;

    @Autowired
    private RedisOps redisOps;

    @Override
    public void handlerResult(IPage<UserAccount> page) {
        // 想让返回值实现自动回显，请将此行代码打开
        // echoService.action(page);
    }

    /**
     * Excel导入后的操作
     *
     * @param list
     */
    @Override
    public R<Boolean> handlerImport(List<Map<String, String>> list) {
        List<UserAccount> userAccountList = list.stream().map((map) -> {
            UserAccount userAccount = UserAccount.builder().build();
            //TODO 请在这里完成转换
            return userAccount;
        }).collect(Collectors.toList());

        return R.success(baseService.saveBatch(userAccountList));
    }


    /**
     * 注册
     *
     * @param userAccountDto 用户新增实体
     *                       //     * @param sysUser        全局变量实体
     * @return
     */
    @ApiOperation(value = "注册", notes = "注册")
    @PostMapping("/register")
//    public R<UserAccountVo> register(@RequestBody UserAccountDto userAccountDto, @ApiIgnore @LoginUser SysUser sysUser) {
    public R<UserAccountVo> register(@RequestBody UserAccountDto userAccountDto) {
        if (userAccountDto.getProjectId() == null) {
            userAccountDto.setProjectId(ContextUtil.getProjectId());
        }
        return userAccountService.register(userAccountDto);
    }

    /**
     * 添加用户
     *
     * @param userAccountDto 用户新增实体
     * @return
     */
    @ApiOperation(value = "添加用户", notes = "添加用户")
    @PostMapping("/saveUser")
    public R<UserAccountVo> saveUser(@RequestBody UserAccountDto userAccountDto) {
        if (userAccountDto.getProjectId() == null) {
            userAccountDto.setProjectId(ContextUtil.getProjectId());
        }
        // TODO: 2021/11/2 暂时无需求，和注册一样，但得分开
        return userAccountService.register(userAccountDto);
    }

    /**
     * 添加公司用户
     *
     * @param userAccountDto 用户新增实体
     * @return
     */
    @ApiOperation(value = "添加公司用户", notes = "添加公司用户")
    @PostMapping("/saveCompanyUser")
    public R<UserAccountVo> saveCompanyUser(@RequestBody UserAccountDto
                                                    userAccountDto) {

        if (userAccountDto.getProjectId() == null) {
            userAccountDto.setProjectId(ContextUtil.getProjectId());
        }
        // TODO: 2021/11/2 暂时无需求，和注册一样，但得分开
        return userAccountService.registerOfCompany(userAccountDto);
    }

    /**
     * 给其他项目创建管理员
     *
     * @param userAccountDto 用户新增实体
     * @return
     */
    @ApiOperation(value = "给其他项目创建管理员", notes = "给其他项目创建管理员")
    @PostMapping("/addAdminUser")
    public R<UserAccountVo> addAdminUser(@RequestBody UserAccountDto userAccountDto) {
        return userAccountService.addAdminUser(userAccountDto);
    }

    /**
     * 登录
     *
     * @param userAccountDto 用户登录实体
     * @return
     */
    @ApiOperation(value = "登录", notes = "登录")
    @PostMapping("/login")
    public R<UserAccountVo> login(@RequestBody UserAccountDto userAccountDto) {
        //全库查询用户信息
        UserAccountDto userAccountDto2 = new UserAccountDto();
        userAccountDto2.setName(userAccountDto.getName());
        List<UserAccount> userAccountList = userAccountService.getUserByNameAllDb(userAccountDto2);
        if (userAccountList != null && !userAccountList.isEmpty()) {
            //设置项目id
            ContextUtil.setProjectId(userAccountList.get(0).getProjectId());
            //切换多数据源
            ContextUtil.setTenant(tenantUtil.getTenant());
        }

        R<UserAccountVo> userAccountVoR = userAccountService.login(userAccountDto);
        //判断用户登录方式
        return verifyLogin(userAccountVoR, userAccountDto.getSubjectType());
    }

    public R<UserAccountVo> verifyLogin(R<UserAccountVo> userAccountVoR, SubjectTypeEnum subjectTypeEnum) {
        if (subjectTypeEnum == null) {
            return userAccountVoR;
        }
        if (userAccountVoR.getCode() == SUCCESS_CODE) {
            //判断用户登录方式
            UserAccountVo userAccountVo = userAccountVoR.getData();
            if (SubjectTypeEnum.ACTOR.getCode().equals(subjectTypeEnum.getCode()) && (userAccountVo.getIsActor() == null || 1 != userAccountVo.getIsActor())) {
                return R.fail(JWT_PARSER_TOKEN_FAIL);
            } else if (SubjectTypeEnum.VISITOR.getCode().equals(subjectTypeEnum.getCode()) && (userAccountVo.getIsVisitor() == null || 1 != userAccountVo.getIsVisitor())) {
                return R.fail(JWT_PARSER_TOKEN_FAIL);
            }
            userAccountVo.setSubjectType(subjectTypeEnum);
            return R.success(userAccountVo);
        }
        return userAccountVoR;
    }

    /**
     * 手机号登录
     *
     * @param userAccountDto 用户登录实体
     * @return
     */
    @ApiOperation(value = "手机号登录", notes = "手机号登录")
    @PostMapping("/loginOfMobile")
    public R<UserAccountVo> loginOfMobile(@RequestBody UserAccountDto userAccountDto) {
        //校验手机验证码
//        String verifyValue = redisOps.get(userAccountDto.getVerifyId());
//        if(StringUtils.isBlank(userAccountDto.getVerifyValue()) || !userAccountDto.getVerifyValue().equals(verifyValue)){
//            return R.fail(ExceptionCode.ERROR_VERIFY);
//        }
        //全库查询用户信息
        UserAccountDto userAccountDto2 = new UserAccountDto();
        userAccountDto2.setMobile(userAccountDto.getMobile());
        List<UserAccount> userAccountList = userAccountService.getUserByNameAllDb(userAccountDto2);
        if (userAccountList != null && !userAccountList.isEmpty()) {
            //设置项目id
            ContextUtil.setProjectId(userAccountList.get(0).getProjectId());
            //切换多数据源
            ContextUtil.setTenant(tenantUtil.getTenant());
        }
        R<UserAccountVo> userAccountVoR = userAccountService.loginOfMobile(userAccountDto);
        //判断用户登录方式
        return verifyLogin(userAccountVoR, userAccountDto.getSubjectType());
    }


    /**
     * 邮箱登录
     *
     * @param userAccountDto 用户登录实体
     * @return
     */
    @ApiOperation(value = "邮箱登录", notes = "邮箱登录")
    @PostMapping("/loginOfEmail")
    public R<UserAccountVo> loginOfEmail(@RequestBody UserAccountDto userAccountDto) {
        //校验手机验证码
        //全库查询用户信息
        UserAccountDto userAccountDto2 = new UserAccountDto();
        userAccountDto2.setEmail(userAccountDto.getEmail());
        List<UserAccount> userAccountList = userAccountService.getUserByNameAllDb(userAccountDto2);
        if (userAccountList != null && !userAccountList.isEmpty()) {
            //设置项目id
            ContextUtil.setProjectId(userAccountList.get(0).getProjectId());
            //切换多数据源
            ContextUtil.setTenant(tenantUtil.getTenant());
        }
        R<UserAccountVo> userAccountVoR = userAccountService.loginOfEmail(userAccountDto);
        //判断用户登录方式
        return verifyLogin(userAccountVoR, userAccountDto.getSubjectType());
    }

    /**
     * 登出
     *
     * @param id 用户id
     * @return
     */
    @ApiOperation(value = "登出", notes = "登出")
    @GetMapping("/loginOut")
    public R loginOut(Long id) {
        return userAccountService.loginOut(id);
    }

    /**
     * 查询用户所有角色和菜单
     *
     * @param userId 用户id
     * @return
     */
    @ApiOperation(value = "查询用户所有角色和菜单", notes = "查询用户所有角色和菜单")
    @GetMapping("/findOrgRoleOfUserId")
    @BaseControllerInfo(voGroup = {VoGroupClass.findMenuOrFunctionById.class})
    public R<UserAccountVo> findOrgRoleOfUserId(Long userId) {
        UserAccountVo userAccountVo = baseService.findOrgRoleOfUserId(userId);
        return R.success(userAccountVo);

    }


    /**
     * 查询用户所有角色和菜单
     *
     * @return
     */
    @ApiOperation(value = "查询用户所有角色和菜单", notes = "查询用户所有角色和菜单")
    @GetMapping("/getById")
    public R<UserAccountVo> getById(@RequestParam("userId") Long userId) {
        if (userId == null) {
            userId = ContextUtil.getUserId();
        }
        return baseService.findById(userId);
    }

    /**
     * 查询用户所有角色和菜单前端用
     *
     * @return
     */
    @ApiOperation(value = "查询用户所有角色和菜单前端用", notes = "查询用户所有角色和菜单前端用")
    @GetMapping("/getByIdLead")
    public R<UserAccountVo> getByIdLead() {
        return baseService.findById(ContextUtil.getUserId());
    }


    /**
     * 批量查询用户简单信息
     *
     * @param userAccountDto
     * @return
     */
    @ApiOperation(value = "查询用户信息", notes = "查询用户信息")
    @PostMapping("/querySimpleByIds")
    public R<List<UserAccountVo>> querySimpleByIds(@RequestBody @Validated({UserAccountDto.getByIds.class}) UserAccountDto userAccountDto) {
        return R.success(baseService.listOfUserAccountVo(null, userAccountDto.getUserIds()));
    }


    /**
     * sharding逻辑删除方法 逻辑删除
     * 只做最基本的逻辑删除，如出现其他业务操作请自行添加功能
     *
     * @param ids id
     * @return 是否成功
     */
    @ApiOperation(value = "sharding逻辑删除")
    @DeleteMapping("/removeByIdsOfLogicOfSharding")
    public R removeByIdsOfLogicOfSharding(@RequestBody List<Long> ids) {
        return baseService.removeByIdsOfLogicOfSharding(ids);
    }


    /**
     * 修改用户信息
     *
     * @param userAccountDto
     * @return
     */
    @ApiOperation(value = "修改用户信息", notes = "修改用户信息")
    @PutMapping("/updateById")
    public R<Boolean> updateById(@RequestBody @Validated({UserAccountDto.updateById.class}) UserAccountDto userAccountDto) {
        return baseService.updateById(userAccountDto);
    }



    /**
     * 修改公司用户信息
     *
     * @param userAccountDto
     * @return
     */
    @ApiOperation(value = "修改公司用户信息", notes = "修改公司用户信息")
    @PutMapping("/updateByIdOfCompany")
    public R<Boolean> updateByIdOfCompany(@RequestBody UserAccountDto userAccountDto) {
        return baseService.updateByIdOfCompany(userAccountDto);
    }



    /**
     * 添加用户信息
     *
     * @param userAccountDto
     * @return
     */
    @ApiOperation(value = "添加用户信息", notes = "添加用户信息")
    @PostMapping("/addUser")
    public R<Boolean> addUser(@RequestBody UserAccountDto userAccountDto) {
        return baseService.updateById(userAccountDto);
    }


    /**
     * 设置密码
     *
     * @param userUpdPassParam
     * @return
     */
    @ApiOperation(value = "设置密码", notes = "设置密码")
    @PostMapping("/setPassword")
    public R<Boolean> setPassword(@RequestBody UserUpdPassParam userUpdPassParam) {
        return baseService.updPassword(userUpdPassParam);
    }


    /**
     * 修改密码
     *
     * @param userUpdPassParam
     * @return
     */
    @ApiOperation(value = "修改密码", notes = "修改密码")
    @PostMapping("/updPassword")
    public R<Boolean> updPassword(@RequestBody UserUpdPassParam userUpdPassParam) {
        return baseService.updPassword(userUpdPassParam);
    }


    /**
     * 重置密码
     *
     * @param userAccountDto
     * @return
     */
    @ApiOperation(value = "重置密码", notes = "重置密码")
    @PostMapping("/initPassword")
    public R<Boolean> initPassword(@RequestBody UserAccountDto userAccountDto) {
        return baseService.initPassword(userAccountDto.getId());
    }


    /**
     * 根据邮箱和手机号查询用户信息
     *
     * @param mobile 用户id
     * @param email  手机号
     * @return
     */
    @ApiOperation(value = "根据邮箱和手机号查询用户信息", notes = "根据邮箱和手机号查询用户信息")
    @GetMapping("/queryOfPhoneOrEmail")
    @BaseControllerInfo(voGroup = {VoGroupClass.findMenuOrFunctionById.class})
    public R<UserAccount> queryOfPhoneOrEmail(String mobile, String email) {
        UserAccountDto userAccountDto = new UserAccountDto();
        userAccountDto.setEmail(email);
        userAccountDto.setMobile(mobile);
        List<UserAccount> userAccountList = baseService.listOfPhoneOrEmail(userAccountDto);
        if (userAccountList != null && !userAccountList.isEmpty()) {
            return R.success(userAccountList.get(0));
        }
        return R.success(null);
    }


    /**
     * 成为展商，观众
     *
     * @param userAccountDto
     * @return
     */
    @ApiOperation(value = "成为展商，观众", notes = "成为展商，观众")
    @PostMapping("/initRole")
    public R<UserAccountVo> initRole(@RequestBody UserAccountDto userAccountDto) {
        return baseService.initRole(userAccountDto);
    }


    /**
     * 测试
     *
     * @return
     */
    @ApiOperation(value = "测试", notes = "测试")
    @GetMapping("/test")
    public R<String> test() {
        log.info("test is execute");
        companyServiceFeign.test(111L);
//        try {
//            Thread.sleep(120000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        return R.success(null);
    }


    /**
     * 检验是否有权限
     *
     * @param userId
     * @param permission
     * @return
     */
    @ApiOperation(value = "检验是否有权限", notes = "检验是否有权限")
    @GetMapping("/isPermission")
    public R<Boolean> isPermission(@RequestParam("userId") Long userId, @RequestParam("permission") String[] permission) {
        return R.success(organizationService.isPermission(userId, permission));
    }


    /**
     * 修改关联信息（观众id，展商id，公司id）
     *
     * @param userAccountDto
     * @return
     */
    @ApiOperation(value = "修改关联信息", notes = "修改关联信息")
    @PostMapping("/updateCorrelationById")
    public R<Boolean> updateCorrelationById(@RequestBody UserAccountDto userAccountDto) {
        UserAccount userAccount = baseService.getById(userAccountDto.getId());
        if (userAccount == null) {
            return R.success(false);
        }
        if (userAccountDto.getCompanyId() != null) {
            userAccount.setCompanyId(userAccountDto.getCompanyId());
        }
        if (userAccountDto.getExhibitorId() != null) {
            userAccount.setExhibitorId(userAccountDto.getExhibitorId());
        }
        if (userAccountDto.getVisitorId() != null) {
            userAccount.setVisitorId(userAccountDto.getVisitorId());
        }
        if (StringUtils.isNotBlank(userAccountDto.getNickName())) {
            userAccount.setNickName(userAccountDto.getNickName());
        }
        return R.success(baseService.updateById(userAccount));
    }


}
